#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <signal.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <fstream>

using namespace std;

class Server{
    public:

    //Estructura para manejar el puerto de conexión
    struct servent *port;
    //Descriptores de archivo para el socket y la conexión
    int socketFD, connectionFD;
    socklen_t len;
    //dato a recibir
    int data;

    char ch, buff[INET_ADDRSTRLEN];
    //Estructuras para el manejo de direcciones inet
    struct sockaddr_in socketAddress, connectionAddress;

    //Constructor
    Server(char *service_name){

        //Obtener puerto de conexion del archivo /etc/service usando el nombre del servicio
        //y el protocolo del mismo
        port=getservbyname(service_name,"tcp");
        //Crear el socket
        socketFD= socket(AF_INET, SOCK_STREAM, 0);

        //Terminar la ejecución si no se ha creado el descriptor del socket correctamente
        //De lo contrario iniciar el socket
        if(socketFD<0){
            perror("No se pudo iniciar el servidor");
            _exit(-1);
        }else{
            //saveData('g',0);
            startSocket();
        }
    }

    private:
    int startSocket(){

        //Definimos las propiedades del socket
        socketAddress.sin_family=AF_INET;
        socketAddress.sin_addr.s_addr=INADDR_ANY;
        socketAddress.sin_port=port->s_port;

        //Asociamos el socket con un puerto para que escuche peticiones a traves del mismo
        bind(socketFD, (struct sockaddr *)&socketAddress, sizeof(socketAddress));

        //Le indicamos al socket que inicie a escuchar peticiones y especificamos un
        //tamaño de cola de conexiones
        listen(socketFD, 5);

        int n=0;

        printf("%s\n", "aaaaaaaaaaaaahhhhhhhhhhhhhhh");

        int connected=1;
        while(connected) {
            printf("Server waiting\n");

            len=sizeof(connectionAddress);

            //Aceptar una conexión
            connectionFD=accept(socketFD, (struct sockaddr *)&connectionAddress, &len);

            //Lanzar un hilo en el sistema para que atienda la nueva conexion
            pid_t pid=fork();

            if(pid) {

                n++;
                printf("Child Server Created Handling connection with %s\n",
                    inet_ntop(AF_INET, &connectionAddress.sin_addr, buff, sizeof(buff)));

                //Dado que el hilo hijo atiende esta peticion cerramos el socket para el padre
                close(socketFD);

                //Mientras se reciban datos desde el cliente se guardaran en un archivo
                printf("%s\n","buuu" );

                while(read(connectionFD, &ch, 1)>0){
                    saveData(ch,n);
                }
                //Cuando se deje de recibir informacion se entenderá que el cliente se ha desconectado
                //y se cerrara la conexion en el servidor hijo y finalizando dicho hilo
                close(connectionFD);
                return 0;
            }
            //Cerrar el socket totalmente
            printf("%s\n","baaaaaaaaa" );
            close(connectionFD);
            connected=0;
        }

    }

    void saveData(char data,int n){
        FILE *file;
        file = fopen("car"+n,"w");
        fprintf(file,"%c",data);
        fclose(file); /*done!*/
    }
};

int main(int argc, char *argv[]){
    Server serverSocket = Server((char*)"my_service");
}